package com.LachesismStorm.lachesism.member.service.impl;


import com.LachesismStorm.lachesism.core.exception.Asserts;
import com.LachesismStorm.lachesism.core.service.RedisService;
import com.LachesismStorm.lachesism.core.util.JwtTokenUtil;
import com.LachesismStorm.lachesism.core.util.LachesismTools;
import com.LachesismStorm.lachesism.core.util.SendMessage;
import com.LachesismStorm.lachesism.member.dto.UmsMemberParam;
import com.LachesismStorm.lachesism.member.mapper.UmsUserMapper;
import com.LachesismStorm.lachesism.member.service.UmsMemberService;
import com.LachesismStorm.lachesism.member.util.AesTool;
import com.LachesismStorm.lachesism.member.util.MemberUtil;
import com.LachesismStorm.lachesism.member.vo.MemberDetails;
import com.LachesismStorm.lachesism.member.vo.MessageVO;
import com.LachesismStorm.lachesism.member.vo.NoteVO;
import com.LachesismStorm.lachesism.member.vo.UmsMember;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import static com.LachesismStorm.lachesism.core.common.enums.ResponseCodeEnum.NOTFOUND;
import static com.LachesismStorm.lachesism.websocket.WebSocketService.broadcast;


@Service
public class UmsMemberServiceImpl implements UmsMemberService {
    @Resource
    private UmsUserMapper umsUserMapper;
    @Resource
    private PasswordEncoder passwordEncoder;
    @Resource
    private JwtTokenUtil jwtTokenUtil;
    @Resource
    private RedisService redisService;

    @Value("${aes.key}")
    private String key;


    @Override
    public String loginByPhone(UmsMemberParam memberParam) {
        Integer count = umsUserMapper.getUserExists(memberParam);
        if (count == 0 && memberParam.getPassword() != null && memberParam.getCode() == null) {
            Asserts.fail(NOTFOUND);
        }
        checkMessageCode(memberParam);
        if (memberParam.getPassword() == null) {
            memberParam.setPassword(memberParam.getPhone());
        }

        if (count == 0) {
            register(memberParam);
        }
        return login(memberParam);

    }


    @Override
    public void sendMessage(UmsMemberParam memberParam) {
        String phone = "";
        String code = LachesismTools.generateRandomCode(); // 生成一个随机的四位数验证码
        try {
            phone = LachesismTools.decrypt(memberParam.getPhone());
        } catch (Exception e) {
            // 记录错误或抛出自定义异常
            Asserts.fail("参数校验失败");
        }
        try {
            SendMessage.sendMessage(code, phone);
            redisService.set(phone, code, 5, TimeUnit.MINUTES);
        } catch (Exception e) {
            // 记录错误或抛出自定义异常
            Asserts.fail("操作失败");
        }
    }

    @Override
    public UmsMember getUserInfo() {
        UmsMember userInfo = MemberUtil.getUserInfo();
        return userInfo;
    }

    @Override
    public void updateMemberInfo(UmsMember member) {
        umsUserMapper.updateMemberInfo(member);
    }

    @Override
    public void sendAMessage(MessageVO messageVO) {
        try {
            String message = LachesismTools.decrypt(messageVO.getMessage());
            Integer userId = MemberUtil.getUserId();
            umsUserMapper.addMessageLog(message, userId);
            broadcastMessage(message);
        } catch (Exception e) {
            Asserts.fail("校验没通过");
        }
    }


    private void broadcastMessage(String message) {
        UmsMember userInfo = MemberUtil.getUserInfo();
        MessageVO messageVO = new MessageVO();
        messageVO.setMessage(message);
        messageVO.setAvatar(userInfo.getIcon());
        messageVO.setNickName(userInfo.getNickName());
        messageVO.setSendTime(new Date());
        messageVO.setUserId(userInfo.getId());
        try {
            String sendMessage = AesTool.encryptEntity(messageVO);
            broadcast(sendMessage);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public UserDetails loadUserByUsername(String phone) {
        UmsMember member = umsUserMapper.getMemberInfo(phone);
        if (member != null) {
            return new MemberDetails(member);
        }
        return null;
    }

    private void checkMessageCode(UmsMemberParam memberParam) {
        if (memberParam.getCode() == null) {
            return;
        }
        String storedCode = (String) redisService.getWithTimeout(memberParam.getPhone());
        if (storedCode == null || !storedCode.equals(memberParam.getCode())) {
            Asserts.fail("验证码错误");
        }
    }


    private void register(UmsMemberParam memberParam) {
        String password = memberParam.getPhone();
        String encodePassword = passwordEncoder.encode(password);
        memberParam.setPassword(encodePassword);
        umsUserMapper.register(memberParam);
    }

    private String login(UmsMemberParam memberParam) {
        UserDetails userDetails = loadUserByUsername(memberParam.getPhone());
        if (userDetails == null) {
            Asserts.fail("用户不存在");
        }
        if (!passwordEncoder.matches(memberParam.getPassword(), userDetails.getPassword())) {
            Asserts.fail("密码错误");
        }
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        return jwtTokenUtil.generateToken(userDetails);
    }
}